﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Net.Http;
using System.Web.Http;
using VaccineEbook.Models;
using VaccineEbook.Models.DBEntity;
using VaccineEbook.Common;
using System.Data.Entity.Validation;
using System.Diagnostics;

namespace VaccineEbook.Controllers
{
    public class MobileUserController : ApiController
    {
        
        VaccineEBookEntities _db = new VaccineEBookEntities();
        // GET api/mobileuser

        #region [View]
        [HttpGet]
        [ActionName("GetAll")]
        public IEnumerable<User> GetAll()
        {
            try
            {
                var _user = (from u in _db.Users select u);
                IEnumerable<User> user = _user.ToList().AsQueryable();
                if (user != null)
                {
                    return user;
                }
                else
                    return null;
            }
            catch
            {
                return null;
            }
        }

        [HttpGet]
        [ActionName("GetAllUser")]
        public HttpResponseMessage GetAllUser()
        {
            try
            {
                var _user = (from u in _db.Users  select u);
                IEnumerable<User> user = _user.ToList().AsQueryable();
                if (user != null)
                {
                    return Request.CreateResponse<IEnumerable<User>>(HttpStatusCode.OK, user);
                }
                else
                    return Request.CreateResponse(HttpStatusCode.NotFound);
            }
            catch
            {
                return Request.CreateResponse(HttpStatusCode.BadGateway);
            }

        }

        // GET api/user/5        
        public HttpResponseMessage GetUser(int id)
        {

            if (string.IsNullOrEmpty(id.ToString()))
            {
                return Request.CreateErrorResponse(HttpStatusCode.NoContent, MESSAGE_STRING.EMPTY_DATA);


            }
            try
            {
                //User user = _db.Users.Where(u => u.UserID == id).Single();
                //if (user != null)
                //{
                //    return Request.CreateResponse<IEnumerable<User>>(HttpStatusCode.OK, user);
                //}
                //else
                //{
                return Request.CreateResponse(HttpStatusCode.NotFound);
                //}

            }
            catch
            {
                return Request.CreateResponse(HttpStatusCode.BadGateway);
            }
        }


        [HttpGet]
        [ActionName("GetAllVaccine")]
        public HttpResponseMessage GetAllVaccine()
        {
            try
            {
                var _vaccine = (from u in _db.Vaccines where u.Status == (int)STATUS_OBJECT.ACTIVE select u);
                IEnumerable<Vaccine> vaccine = _vaccine.ToList().AsQueryable();
                if (vaccine != null)
                {
                    return Request.CreateResponse<IEnumerable<Vaccine>>(HttpStatusCode.OK, vaccine);
                }
                else
                    return Request.CreateResponse(HttpStatusCode.NotFound);
            }
            catch
            {
                return Request.CreateResponse(HttpStatusCode.BadGateway);
            }

        }

        [HttpGet]
        [ActionName("GetAllVaccineRecord")]
        public HttpResponseMessage GetAllVaccineRecord(int userID)
        {
            if (string.IsNullOrEmpty(userID.ToString()))
                return Request.CreateErrorResponse(HttpStatusCode.NotModified, MESSAGE_STRING.EMPTY_DATA);
            MobileModel.Result mode = new MobileModel.Result();
            try
            {
                var _vaccineRecord = (from v in _db.VaccineRecords where v.UserID == userID select v);
                IEnumerable<VaccineRecord> vaccineRecord = _vaccineRecord.ToList().AsQueryable();
                if (vaccineRecord != null)
                {
                    foreach(VaccineRecord vc in vaccineRecord)
                    {
                        if (vc.VaccineName == null) vc.VaccineName = string.Empty;
                        if (vc.DiseaseName == null)
                            vc.DiseaseName = string.Empty;
                        else
                            vc.DiseaseName = EncryptionUtil.Decode(vc.DiseaseName, vc.UserID.ToString().Trim().ToLower());
                        if (vc.Note == null)
                            vc.Note = string.Empty;                        
                        else
                            vc.Note = EncryptionUtil.Decode(vc.Note, vc.UserID.ToString().Trim().ToLower());
                    }
                    mode.Status = HttpStatusCode.Accepted.ToString();
                    mode.Id = userID.ToString();
                    mode.Message = MESSAGE_STRING.GET_DATA_SUCCESSFUL;
                    return Request.CreateResponse<IEnumerable<VaccineRecord>>(HttpStatusCode.OK, vaccineRecord);
                }
                else
                {
                    mode.Status = HttpStatusCode.NotFound.ToString();                    
                    mode.Message = MESSAGE_STRING.EMPTY_DATA;
                    return Request.CreateResponse(HttpStatusCode.NotFound,mode);
                }
            }
            catch
            {
                mode.Status = HttpStatusCode.BadGateway.ToString();
                mode.Message = MESSAGE_STRING.CONNECTION_FAIL;
                return Request.CreateResponse(HttpStatusCode.BadGateway,mode);
            }

        }

        [HttpGet]
        [ActionName("GetVaccineRecord")]
        public HttpResponseMessage GetVaccineRecord(int vaccineRecordID)
        {
            if(string.IsNullOrEmpty(vaccineRecordID.ToString()))
                return Request.CreateErrorResponse(HttpStatusCode.NotModified, MESSAGE_STRING.EMPTY_DATA);
            MobileModel.Result mode = new MobileModel.Result();
            try
            {
                VaccineRecord vaccineRecord = _db.VaccineRecords.Where(v => v.VaccineRecordID == vaccineRecordID).SingleOrDefault();
              //  VaccineRecord vaccineRecord = (from v in _db.VaccineRecords where v.VaccineRecordID == vaccineRecordID select v);
                if (vaccineRecord != null)
                {
                    mode.Status = HttpStatusCode.Accepted.ToString();
                    mode.Id = vaccineRecord.VaccineRecordID.ToString();
                    mode.Message = MESSAGE_STRING.GET_DATA_SUCCESSFUL;
                    vaccineRecord.DiseaseName =  EncryptionUtil.Decode(vaccineRecord.DiseaseName,vaccineRecord.UserID.ToString().Trim());
                    vaccineRecord.Note = EncryptionUtil.Decode(vaccineRecord.Note,vaccineRecord.UserID.ToString().Trim());
                    return Request.CreateResponse(HttpStatusCode.OK, vaccineRecord);
                }
                else
                {
                    mode.Status = HttpStatusCode.NotFound.ToString();                    
                    mode.Message = MESSAGE_STRING.EMPTY_DATA;
                    return Request.CreateResponse(HttpStatusCode.NotFound,mode);
                }
            }
            catch(Exception ex)
            {
                mode.Status = HttpStatusCode.BadGateway.ToString();                
                mode.Message = MESSAGE_STRING.CONNECTION_FAIL;
                return Request.CreateResponse(HttpStatusCode.BadGateway,mode);
            }
        }

        [HttpGet]
        [ActionName("GetBook")]
        public HttpResponseMessage GetBook(int userID) 
        {
            if (string.IsNullOrEmpty(userID.ToString()))
                return Request.CreateErrorResponse(HttpStatusCode.NotModified, MESSAGE_STRING.EMPTY_DATA);
            MobileModel.ResultBook mode  = new MobileModel.ResultBook();
            try
            {                
                var _chapter = (from ch in _db.Chapters  select ch );
                IEnumerable<Chapter> chapter = _chapter.ToList().AsQueryable();
                List< MobileModel.ResultBook> modes = new List<MobileModel.ResultBook>();
                if (chapter != null)
                {       
                    mode.Status = HttpStatusCode.Accepted.ToString();                    
                    mode.Message = MESSAGE_STRING.GET_DATA_SUCCESSFUL;                    
                    mode.Chapter = chapter;
                    foreach (Chapter c in chapter)
                    {                        
                        if (c.Icon == null) c.Icon = string.Empty;
                        if (c.BookID == null) c.BookID = 1;
                        if (c.ChappterGroup == null) c.ChappterGroup = string.Empty; ;
                        if (c.ChapterDescription == null) c.ChapterDescription = string.Empty; ;
                        if (c.ChapterID == null) c.ChapterID = 0;
                        if (c.ChapterContent == null) c.ChapterContent = string.Empty; ;
                        if (c.CreatedBy == null) c.CreatedBy = 1;
                        if (c.Version == null) c.Version = "1";                        
                    }                    
                    return Request.CreateResponse(HttpStatusCode.OK, mode);
                }
                else
                {
                    mode.Status = HttpStatusCode.NotFound.ToString();                    
                    mode.Message = MESSAGE_STRING.EMPTY_DATA;
                    return Request.CreateResponse(HttpStatusCode.NotFound,mode);
                }
            }
            catch (Exception ex)
            {
                mode.Status = HttpStatusCode.BadGateway.ToString();
                mode.Message = MESSAGE_STRING.CONNECTION_FAIL;
                return Request.CreateResponse(HttpStatusCode.BadGateway ,mode);
            }
        }

        #endregion

        #region [Login/Register]

        // POST api/user
        public void Post([FromBody]string value)
        {
        }

        [HttpPost]
        public HttpResponseMessage Login([FromBody] MobileModel.Login login)
        {
            MobileModel.Result mode = new MobileModel.Result();
            try
            {
                if (string.IsNullOrEmpty(login.Password))
                    return Request.CreateErrorResponse(HttpStatusCode.NotModified, MESSAGE_AUTH_STRING.EMPTY_PASSWORD);
                if (string.IsNullOrEmpty(login.UserName))
                    return Request.CreateErrorResponse(HttpStatusCode.NotModified, MESSAGE_AUTH_STRING.EMPTY_USERNAME);                
                string encodePassword = EncryptionUtil.Encode(login.Password, login.UserName.Trim().ToLower());
                User user = _db.Users.Where(u => u.Username == login.UserName).SingleOrDefault();
                if (user != null)
                {
                    if (user.UserStatus != (int)STATUS_USER.MOBILE_ACTIVE)
                        return Request.CreateResponse(HttpStatusCode.Unused);
                    if (user.Password != encodePassword)
                        return Request.CreateResponse(HttpStatusCode.Unauthorized);
                    mode.Status = HttpStatusCode.Accepted.ToString();
                    mode.Id = user.UserID.ToString();
                    mode.Message = MESSAGE_STRING.LOGIN_SUCCESSFUL;
                    return Request.CreateResponse<MobileModel.Result>(HttpStatusCode.Accepted, mode);
                }
                else
                {
                    mode.Status = HttpStatusCode.NotFound.ToString();
                    mode.Message = MESSAGE_AUTH_STRING.UNVALID_LOGIN_USER;
                    return Request.CreateResponse(HttpStatusCode.NotFound,mode);
                }
            }
            catch
            {
                mode.Status = HttpStatusCode.BadGateway.ToString();
                mode.Message = MESSAGE_STRING.EMPTY_DATA;
                return Request.CreateResponse(HttpStatusCode.NotFound,mode);
            }

        }

        [HttpPost]
        public HttpResponseMessage Register([FromBody] MobileModel.Register user)
        {
            MobileModel.Result mode = new MobileModel.Result();
            try
            {
                if (string.IsNullOrEmpty(user.Password))
                    return Request.CreateErrorResponse(HttpStatusCode.NotModified,MESSAGE_AUTH_STRING.EMPTY_PASSWORD);
                if (string.IsNullOrEmpty(user.UserName))
                    return Request.CreateErrorResponse(HttpStatusCode.NotModified, MESSAGE_AUTH_STRING.EMPTY_USERNAME);
                if(string.IsNullOrEmpty(user.ConfirmPassword) || string.Compare(user.Password,user.ConfirmPassword) != 0)
                    return Request.CreateErrorResponse(HttpStatusCode.NotModified, MESSAGE_AUTH_STRING.EMPTY_CONFIRM_PASSWORD);
                
                int existed = CheckData.CheckUser(user.UserName) ;
                if ( existed == 0)
                {
                    mode.Status = "Duplicate";
                    mode.Message = MESSAGE_STRING.USERNAME_EXISTS.ToString();
                    return Request.CreateResponse<MobileModel.Result>(HttpStatusCode.Accepted, mode);
                }
                else if (existed == -2)
                {
                    mode.Status = HttpStatusCode.BadGateway.ToString();
                    mode.Message = MESSAGE_STRING.CONNECTION_FAIL.ToString();
                    return Request.CreateResponse<MobileModel.Result>(HttpStatusCode.BadGateway, mode);
                }
                if (this.ModelState.IsValid && existed == -1)
                {
                    User _user = new User();
                    _user.Username = user.UserName;
                    _user.Password = EncryptionUtil.Encode(user.Password, user.UserName.Trim().ToLower());
                    _user.ConfirmPassword = EncryptionUtil.Encode(user.ConfirmPassword, user.UserName.Trim().ToLower());
                    _user.UserStatus = (int)STATUS_USER.MOBILE_ACTIVE;
                    _user.Status = (int)STATUS_OBJECT.ACTIVE;
                    _user.LastModifined = DateTime.UtcNow;
                    _user.CreatedBy = 1;                    
                    _db.Users.Add(_user);                    
                    //_db.SaveChanges();
                    //_user.CreatedBy = _user.UserID;
                    _db.SaveChanges();
                    if (_user != null)
                    {
                        mode.Id = _user.UserID.ToString();
                        mode.Status = HttpStatusCode.Created.ToString();
                        mode.Message = MESSAGE_STRING.USER_CREATED;
                        var httpRespone = Request.CreateResponse<MobileModel.Result>(HttpStatusCode.Created, mode);
                        string uri = Url.Link("DefaultApi", new { id = mode.Id });
                        httpRespone.Headers.Location = new Uri(uri);
                        return httpRespone;

                    }
                    return Request.CreateResponse(HttpStatusCode.BadRequest,mode);
                }
                else
                    return Request.CreateResponse(HttpStatusCode.NotAcceptable,mode);

            }
            catch (DbEntityValidationException dbEx)           
            {
                foreach (var validationErrors in dbEx.EntityValidationErrors)
                {
                    foreach (var validationError in validationErrors.ValidationErrors)
                    {
                        Trace.TraceInformation("Class: {0}, Property: {1}, Error: {2}", validationErrors.Entry.Entity.GetType().FullName,
                                      validationError.PropertyName, validationError.ErrorMessage);
                    }
                }
                return Request.CreateResponse(HttpStatusCode.BadGateway,mode);
            }
        }

        [HttpPost]
        public HttpResponseMessage CreateVaccineRecord([FromBody] MobileModel.CreateVaccineRecord vaccineRecord)
        {
            MobileModel.ResultCreateVaccineRecord mode = new MobileModel.ResultCreateVaccineRecord();
            try
            {
                if (string.IsNullOrEmpty(vaccineRecord.Note))
                    return Request.CreateErrorResponse(HttpStatusCode.NotModified, MESSAGE_STRING.EMPTY_DATA);
                if (this.ModelState.IsValid)
                {
                    VaccineRecord _vaccineRecord = new VaccineRecord();
                    _vaccineRecord.VaccineID = vaccineRecord.VaccineID;
                  //  _vaccineRecord.DiseaseName = vaccineRecord.DiseaseName;
                    _vaccineRecord.DiseaseName = EncryptionUtil.Encode(vaccineRecord.DiseaseName,"Tan");
                    _vaccineRecord.HadDisease = vaccineRecord.HadDisease  ;
                    _vaccineRecord.Date = vaccineRecord.Date;
                    _vaccineRecord.Note = EncryptionUtil.Encode(vaccineRecord.Note,"Tan");
                    _vaccineRecord.UserID = vaccineRecord.UserID;
                    _vaccineRecord.LastModifined = DateTime.UtcNow;
                    _vaccineRecord.CreatedBy = _vaccineRecord.UserID; 
                    _vaccineRecord.Version = "1";
                    _db.VaccineRecords.Add(_vaccineRecord);
                    _db.SaveChanges();
                    if (_vaccineRecord != null)
                    {
                        mode.Sync_Id = vaccineRecord.Sync_Id.ToString();
                        mode.Server_Id = _vaccineRecord.VaccineID.ToString();
                        mode.Status = HttpStatusCode.Created.ToString();
                        mode.Message = MESSAGE_STRING.VACCINERECORD_CREATED;
                        var httpRespone = Request.CreateResponse<MobileModel.ResultCreateVaccineRecord>(HttpStatusCode.Created, mode);
                        string uri = Url.Link("DefaultApi", new { id = mode.Sync_Id });
                        httpRespone.Headers.Location = new Uri(uri);
                        return httpRespone;
                    }
                    return Request.CreateResponse(HttpStatusCode.BadRequest,mode);
                }
                else
                {
                    foreach (var modelStateVal in ModelState.Values)
                    {
                        foreach (var error in modelStateVal.Errors)
                        {
                            var errorMessage = error.ErrorMessage;
                            var exception = error.Exception;
                            // You may log the errors if you want
                        }
                    }
                    return Request.CreateResponse(HttpStatusCode.NotAcceptable,mode);
                }

            }
            catch (DbEntityValidationException dbEx)
            {
                foreach (var validationErrors in dbEx.EntityValidationErrors)
                {
                    foreach (var validationError in validationErrors.ValidationErrors)
                    {
                        Trace.TraceInformation("Class: {0}, Property: {1}, Error: {2}", validationErrors.Entry.Entity.GetType().FullName,
                                      validationError.PropertyName, validationError.ErrorMessage);
                    }
                }
                return Request.CreateResponse(HttpStatusCode.BadGateway,mode);
            }
        }
       
        [HttpPost]
        public HttpResponseMessage CreateToken([FromBody] MobileModel.Token token)
        {
            MobileModel.ResultTokenId mode = new MobileModel.ResultTokenId();
            try
            {
                if (string.IsNullOrEmpty(token.TokenID))
                    return Request.CreateErrorResponse(HttpStatusCode.NotModified, MESSAGE_STRING.EMPTY_DATA);
                if (string.IsNullOrEmpty(token.UserId.ToString()))
                    return Request.CreateErrorResponse(HttpStatusCode.NotModified, MESSAGE_STRING.EMPTY_DATA);
                int existed = CheckData.CheckTokenID(token.TokenID, token.UserId);
                var errors = ModelState.Values.SelectMany(v => v.Errors);
                if (this.ModelState.IsValid && existed == -1)
                {
                    Token _token = new Token();
                    _token.tokenID = token.TokenID;
                    _token.userID = token.UserId;
                    _token.type = token.Type;
                    _token.LastModifined = DateTime.UtcNow;
                    _db.Tokens.Add(_token);
                    _db.SaveChanges();
                    if (_token != null)
                    {
                        mode.Status = HttpStatusCode.Created.ToString();
                        mode.Message = MESSAGE_STRING.TOKEN_CREATED;
                        var httpRespone = Request.CreateResponse<MobileModel.ResultTokenId>(HttpStatusCode.Created, mode);
                        string uri = Url.Link("DefaultApi", new { id = token.UserId });
                        httpRespone.Headers.Location = new Uri(uri);
                        return httpRespone;                       

                    }
                    return Request.CreateResponse(HttpStatusCode.BadRequest, mode);
                }
                else
                {
                    mode.Status = HttpStatusCode.Found.ToString();
                    mode.Message = "Token is existed!";
                    return Request.CreateResponse(HttpStatusCode.NotAcceptable, mode);
                }                
            }
            catch
            {
                return Request.CreateResponse(HttpStatusCode.BadGateway, mode);
            }            
        }

        
        #endregion

        // PUT api/user/5
        public void Put(int id, [FromBody]string value)
        {
        }

        // DELETE api/user/5
        public void Delete(int id)
        {
        }
     
        [HttpPost]
        public HttpResponseMessage DeleteToken([FromBody] MobileModel.Token token)
        {
            MobileModel.ResultTokenId mode = new MobileModel.ResultTokenId();
            try
            {
                if (string.IsNullOrEmpty(token.TokenID))
                    return Request.CreateErrorResponse(HttpStatusCode.NotModified, MESSAGE_STRING.EMPTY_DATA);
                if (string.IsNullOrEmpty(token.UserId.ToString()))
                    return Request.CreateErrorResponse(HttpStatusCode.NotModified, MESSAGE_STRING.EMPTY_DATA);
                int existed = CheckData.CheckTokenID(token.TokenID, token.UserId);
                if (this.ModelState.IsValid && existed == 0)
                {                    
                    var query = from tk in _db.Tokens
                                where tk.tokenID == token.TokenID
                                select tk;
                   
                    Token _token = query.FirstOrDefault();
                    if (_token != null)
                    {
                        _db.Tokens.Remove(_token);
                        _db.SaveChanges();
                        mode.Status = HttpStatusCode.Accepted.ToString();
                        mode.Message = MESSAGE_STRING.TOKEN_DELETED;
                        return Request.CreateResponse<MobileModel.ResultTokenId>(HttpStatusCode.Accepted, mode);                        
                    }
                    else
                    {
                        mode.Status = HttpStatusCode.OK.ToString();
                        mode.Message = MESSAGE_STRING.EMPTY_DATA;
                        return Request.CreateResponse(HttpStatusCode.BadRequest, mode);
                    }                    
                }
                else
                {
                    mode.Status = HttpStatusCode.Accepted.ToString();
                    mode.Message = MESSAGE_STRING.EMPTY_DATA;
                    return Request.CreateResponse(HttpStatusCode.NotAcceptable, mode);
                }
                    
            }
            catch
            {
                return Request.CreateResponse(HttpStatusCode.BadGateway, mode);
            }
        }
    }
}
